/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.overall;

import com.inspur.edp.bef.component.ICompMethod;
import com.inspur.edp.bef.component.IGspComponent;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.operation.CommonOperation;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import java.util.List;
import java.util.Objects;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

public final class GenUtils {


//  public static String getBinPath(String bePath) {
//    return metadataService.getRefPath(bePath);
//  }

//  public static boolean isMetadataExistInCurrentProject(String metadataId, String currentPath) {
//    return metadataService
//        .isMetadataExistInProject(currentPath, metadataId);
//  }

//  public static Assembly getMetadataAssembly(String metadataId, String currentPath) {
//    return ServiceManager.<MetadataService>GetService().GetAssembly(currentPath, metadataId);
//  }

  public static VariableDeclarationStatement buildVarDeclarationStatement(AST ast, Class type,
      String varName, Expression value){
    VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
    variableDeclarationFragment.setName(ast.newSimpleName(varName));
    variableDeclarationFragment.setInitializer(value);
    VariableDeclarationStatement variableDeclarationStatement = ast.newVariableDeclarationStatement(variableDeclarationFragment);
    variableDeclarationStatement.setType(new TypeInfo(type).getType(ast));
    return variableDeclarationStatement;
  }

  public static VariableDeclarationStatement buildVarDeclarationStatement(AST ast, String typeName,
      String varName, Expression value){
    VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
    variableDeclarationFragment.setName(ast.newSimpleName(varName));
    variableDeclarationFragment.setInitializer(value);
    VariableDeclarationStatement variableDeclarationStatement = ast.newVariableDeclarationStatement(variableDeclarationFragment);
    variableDeclarationStatement.setType(ast.newSimpleType(ast.newName(typeName)));
    return variableDeclarationStatement;
  }

  public static ReturnStatement buildReturnStatement(AST ast, String varName){
    ReturnStatement returnStatement = ast.newReturnStatement();
    returnStatement.setExpression(ast.newSimpleName(varName));
    return returnStatement;
  }

  public static CastExpression buildCastExpression(AST ast, Class type, Expression expression){
CastExpression castExpression = ast.newCastExpression();
castExpression.setType(new TypeInfo(type).getType(ast));
    castExpression.setExpression(expression);
    return castExpression;
  }

  public static CastExpression buildCastExpression(AST ast, String type, Expression expression){
    CastExpression castExpression = ast.newCastExpression();
    castExpression.setType(ast.newSimpleType(ast.newName(type)));
    castExpression.setExpression(expression);
    return castExpression;
  }

  public static ClassInstanceCreation buildClassInstantiation(AST ast, Class type){
    ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
    classInstanceCreation.setType(new TypeInfo(type).getType(ast));
    return classInstanceCreation;
  }

  public static ClassInstanceCreation buildClassInstantiation(AST ast, String type){
    ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
    classInstanceCreation.setType(ast.newSimpleType(ast.newName(type)));
    return classInstanceCreation;
  }

  public static TypeLiteral buildTypeLiteral(AST ast, String typeName){
    TypeLiteral typeLiteral = ast.newTypeLiteral();
    typeLiteral.setType(ast.newSimpleType(ast.newName(typeName)));
    return typeLiteral;
  }

  public static MethodInvocation getMethodInvocation(AST ast, Expression expression ,String method, String... params ) {
    MethodInvocation invocation = ast.newMethodInvocation();
    if (expression != null) {
      invocation.setExpression(expression);
    }
    invocation.setName(ast.newSimpleName(method));
    if(params != null){
      for (String param : params){
        invocation.arguments().add(ast.newName(param));
      }
    }
    return invocation;
  }

  public static StringLiteral buildStringLiteral(AST ast, String value){
    StringLiteral literal = ast.newStringLiteral();
    literal.setLiteralValue(value);
    return literal;
  }

  public static ICompMethod getCompMethod(CommonOperation validation, CefGeneratorContext metadataPool) {
    Objects.requireNonNull(validation, "validation");
    GspMetadata metadata = metadataPool.getMetadata(validation.getComponentPkgName(), validation.getComponentId());
    IGspComponent gspComp;
    if (metadata.getHeader().getType().equals("Component")) {
      gspComp = (IGspComponent) ((metadata.getContent() instanceof IGspComponent) ? metadata
          .getContent() : null);
    } else {
      gspComp = (IGspComponent) ((metadata.getContent() instanceof IGspComponent) ? metadata
          .getContent() : null);
    }

    if (gspComp == null) {
      throw new RuntimeException(validation.getName() + "上构件不存在" + validation.getComponentId());
    }
    return gspComp.getCompMethod();
  }

  public static Expression buildRequestElementsList(AST ast, IGspCommonDataType node, List<String> el) {
    if(el == null || el.isEmpty()) {
      return ast.newNullLiteral();
    }

    MethodInvocation asListInvocation = ast.newMethodInvocation();
    asListInvocation.setName(ast.newSimpleName("asList"));
    QualifiedName name = ast.newQualifiedName(
        ast.newQualifiedName(
            ast.newSimpleName("java"),
            ast.newSimpleName("util")),
        ast.newSimpleName("Arrays"));
    asListInvocation.setExpression(name);
    el.forEach(item -> {
      IGspCommonField field = node.findElement(item);
      if(field == null) {
        throw new RuntimeException(node.getCode()+"上字段不存在"+item);
      }
      asListInvocation.arguments().add(buildStringLiteral(ast, field.getLabelID()));
    });
    return asListInvocation;
  }

}
